﻿#region License
/* ---------------------------------------------------------------- *
 *
 * This file is part of the Xcoordination Application Space
 * ("XcoAppSpace") http://www.xcoordination.com
 *
 * Copyright (C) 2009 Xcoordination http://www.xcoordination.com
 *
 * XcoAppSpace is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General
 * Public License as published by the Free Software Foundation.
 *
 * XcoAppSpace is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see http://www.gnu.org/licenses/
 * or write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * ---------------------------------------------------------------- */
#endregion

using XcoAppSpaces.Contracts.Service;
using XcoAppSpaces.Core.Configuration;

namespace XcoAppSpaces.Core
{
	/// <summary>
	/// Fluent interface for creating an XcoAppSpace and configuring a communication service. 
	/// (This is the fluent base class, which exists to allow implicit conversion to XcoAppSpace via Operators.)
	/// </summary>
	public abstract class XcoFluentServiceConfig : IXcoConfiguration
	{
		/// <summary>
		/// Initialize the service registry used by an appspace instance, depending on the given configuration.
		/// </summary>
		/// <param name="reg">The service registry to be initialized.</param>
		public abstract void InitServiceRegistry(IXcoServiceRegistry reg);
	}

	/// <summary>
	/// Fluent interface for creating an XcoAppSpace and configuring a communication service.
	/// </summary>
	public class XcoFluentServiceConfig<T> : XcoFluentServiceConfig, IXcoFluentConfiguration, IXcoServiceFluentConfiguration<T, XcoFluentServiceConfig<T>>
		where T : IXcoService
	{
		private readonly XcoServiceConfig config;
		private readonly XcoFluentAppSpaceConfig baseConfig;


		internal XcoFluentServiceConfig(XcoFluentAppSpaceConfig baseConfig, XcoServiceConfig config)
		{
			this.baseConfig = baseConfig;
			this.config = config;
		}

		/// <summary>
		/// The service that is getting configured.
		/// </summary>
		public T Service
		{
			get { return (T)config.ConfiguredService; }
		}

		/// <summary>
		/// Additional service configuration information like service name and mappings.
		/// </summary>
		public XcoServiceConfig ServiceConfig
		{
			get { return config; }
		}

		/// <summary>
		/// The configuration itself.
		/// </summary>
		public XcoFluentServiceConfig<T> FluentConfig
		{
			get { return this; }
		}

		/// <summary>
		/// Defines the name of the service. (The name must be unique among all service
		/// instances of the same type, e.g. among all transport services.)
		/// </summary>
		/// <param name="name">The name of the communication service.</param>
		/// <returns>The given XcoServiceConfig instance.</returns>
		public XcoFluentServiceConfig<T> WithName(string name)
		{
			config.Name = name;
			return this;
		}

		/// <summary>
		/// Defines the service to be the default for the space.
		/// </summary>
		/// <returns>The given XcoServiceConfig instance.</returns>
		public XcoFluentServiceConfig<T> AsDefault()
		{
			config.IsDefault = true;
			return this;
		}

		#region IXcoFluentConfiguration Members

		/// <summary>
		/// Defines a certain service instance that should be used by the space.
		/// </summary>
		/// <typeparam name="TS">The type of the service.</typeparam>
		/// <param name="service">The service instance.</param>
		/// <returns>A configuration object that can be used to configure this service instance.</returns>
		public XcoFluentServiceConfig<TS> UsingService<TS>(TS service) where TS : IXcoService
		{
			return baseConfig.UsingService<TS>(service);
		}

		/// <summary>
		/// Defines a certain service instance that should be used by the space. A new service of the given 
		/// type is instantiated. The given type must have a parameterless constructor.
		/// </summary>
		/// <typeparam name="TS">The type of the service.</typeparam>
		/// <returns>A configuration object that can be used to configure this service instance.</returns>
		public XcoFluentServiceConfig<TS> UsingService<TS>() where TS : IXcoService, new()
		{
			return baseConfig.UsingService<TS>(new TS());
		}

		#endregion

		/// <summary>
		/// Initialize the service registry used by an appspace instance, depending on the given configuration.
		/// </summary>
		/// <param name="reg">The service registry to be initialized.</param>
		public override void InitServiceRegistry(IXcoServiceRegistry reg)
		{
			baseConfig.InitServiceRegistry(reg);
		}
	}
}
